// Copyright (C) 2005-2008 Jae Stutzman (jaebird@gmail.com)
//
// This file is part of CastGen.
//
// CastGen is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// CastGen is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with CastGen.  If not, see <http://www.gnu.org/licenses/>.

using System;
using System.IO;
using ID3Lib;

namespace CastGen
{
	public class RSS2Generator
	{
		private const string Title = "TIT2";
		private const string Artist = "TPE1";
		private const string Album = "TALB";
		private const string Comment = "COMM";
		private const string Date = "TDAT";
		private const string Year = "TYER";
		private const string Time = "TIME";

		FileSystemWatcher fsw = new FileSystemWatcher();
		string path;
		string podcastUrl;
		string notesUrl;
		string rssXmlFile;

		string podcastXmlNamespace = string.Empty;
		string podcastXmlDtd = string.Empty;

		string channelTitle = string.Empty;
		string channelDescription = string.Empty;
		string channelCopyright = string.Empty;
		string channelWebmaster = string.Empty;

		public RSS2Generator()
		{
			rssXmlFile = System.Configuration.ConfigurationSettings.AppSettings.Get("PodcastXmlFile");
			path = System.Configuration.ConfigurationSettings.AppSettings.Get("PodcastDirectory");
			podcastUrl = System.Configuration.ConfigurationSettings.AppSettings.Get("PodcastUrl");
			notesUrl = System.Configuration.ConfigurationSettings.AppSettings.Get("NotesUrl");

			podcastXmlNamespace = System.Configuration.ConfigurationSettings.AppSettings.Get("PodcastXmlNamespace");
			podcastXmlDtd = System.Configuration.ConfigurationSettings.AppSettings.Get("PodcastXmlDtd");

			channelTitle = System.Configuration.ConfigurationSettings.AppSettings.Get("ChannelTitle");
			channelDescription = System.Configuration.ConfigurationSettings.AppSettings.Get("ChannelDescription");
			channelCopyright = System.Configuration.ConfigurationSettings.AppSettings.Get("ChannelCopyright");
			channelWebmaster = System.Configuration.ConfigurationSettings.AppSettings.Get("ChannelWebmaster");
		}

		public void Start()
		{
			GenerateNewRSS();

			fsw.Path = path;
			fsw.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.DirectoryName | NotifyFilters.FileName;
			fsw.Changed += new FileSystemEventHandler(OnChanged);
			fsw.Created += new FileSystemEventHandler(OnChanged);
			fsw.Deleted += new FileSystemEventHandler(OnChanged);
			fsw.Renamed += new RenamedEventHandler(OnRenamed);
			fsw.EnableRaisingEvents = true;
		}

		public void Stop()
		{
			fsw.Dispose();
		}

		public void OnChanged(object _o, FileSystemEventArgs fileSystemEventArgs)
		{
			if (fileSystemEventArgs.Name != rssXmlFile)
			{
				Console.WriteLine(fileSystemEventArgs.Name);
				GenerateNewRSS();
			}
		}

		public void OnRenamed(object _o, RenamedEventArgs renamedEventArgs)
		{
			if (renamedEventArgs.Name != rssXmlFile)
			{
				Console.WriteLine(renamedEventArgs.Name);
				GenerateNewRSS();
			}
		}

		private void GenerateNewRSS()
		{
			// create a RSS feed generator for the output
			//FileStream stream = new FileStream(Path.Combine(path, rssXmlFile), FileMode.Create, FileAccess.ReadWrite);
			StreamWriter sr = File.CreateText(Path.Combine(path, rssXmlFile));

			RSSFeedGenerator gen = new RSSFeedGenerator(sr);
			gen.WriteStartDocument(podcastXmlNamespace, podcastXmlDtd);
			gen.WriteStartChannel(channelTitle, podcastUrl, channelDescription, channelCopyright,
				channelWebmaster);

			string[] files = Directory.GetFiles(path, "*.mp3");

			// loop backwords so latest podcast is on the top...
			for (int index = files.Length - 1; index >= 0; index--)
			{
				string filename = files[index];

				try
				{
					string artist = string.Empty;
					string title = string.Empty;
					string album = string.Empty;
					string comment = string.Empty;
					DateTime publishedDate = DateTime.Now;

					GetInfo(filename, ref artist, ref title, ref album, ref comment, ref publishedDate);

					FileInfo info = new FileInfo(filename);

					// we are using Plone and the short name (which is the url) is lowercase and spaces are "-"s
					string albumPath = album.Trim().ToLower().Replace(" ", "-");
					string pageName = Path.GetFileNameWithoutExtension(info.Name).ToLower();
					string link = UrlCombine(UrlCombine(notesUrl, albumPath), pageName);

					// generate the items here
					gen.WriteItem(title, link, comment, artist, publishedDate, album,
						podcastUrl + info.Name, info.Length.ToString());
				}
				catch (Exception e)
				{
					Console.WriteLine(e.Message);
				}

			}
			// clear up
			gen.WriteEndChannel();
			gen.WriteEndDocument();
			gen.Close();
		}

		private void GetInfo(string filename, ref string artist, ref string title,
			ref string album, ref string comment, ref DateTime publishedDate)
		{
			int min = 0;
			int hour = 0;
			int day = 0;
			int month = 0;
			int year = 0;

			MP3File file = new MP3File();
			TagModel tagModel = file.Read(filename);


			foreach (FrameBase frameBase in tagModel.Frames)
			{
				switch (frameBase.Tag)
				{
					case Title:
					{
						title = frameBase.ToString();
						break;
					}
					case Artist:
					{
						artist = frameBase.ToString();
						break;
					}
					case Album:
					{
						album = frameBase.ToString();
						break;
					}
					case Time:
					{
						string time = frameBase.ToString();
						hour = Convert.ToInt32(time.Substring(0, 2));
						min = Convert.ToInt32(time.Substring(2, 2));
						break;
					}
					case Date:
					{
						string date = frameBase.ToString();
						day = Convert.ToInt32(date.Substring(0, 2));
						month = Convert.ToInt32(date.Substring(2, 2));
						break;
					}
					case Year:
					{
						year = Convert.ToInt32(frameBase.ToString());
						break;
					}
					case "TCOM":
					{
						break;
					}
					case "TCON":
					{
						// content type (genere)
						break;
					}
					case "TRCK":
					{
						// track number
						break;
					}
					case "USLT":
					{
						// lyrics
						break;
					}
					case Comment:
					{
						FrameLCText lcFrame = (FrameLCText)(frameBase);
						comment = lcFrame.Text;
						//TODO: add --> lcFrame.Language;
						break;
					}
					case "APIC":
					{
						// picture
						break;
					}
				}
			}

			if (year > 0 && month > 0 && day > 0)
			{
				publishedDate = new DateTime(year, month, day, hour, min, 0);
				//publishDate = dateTime.ToString("r");
			}
		}

		private string UrlCombine(string urlPath1, string urlPath2)
		{
			return urlPath1.TrimEnd('/') + "/" + urlPath2.TrimStart('/');
		}
	}
}
